﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BYServer.SocketEventArgs;
using System.Net;
using System.Net.Sockets;
using FilterData;
using Common;

namespace BYServer
{
    public class MachineConnection
    {
        Socket sock;
        IPAddress ipaddr_machine;
        int port_machine;

        byte[] buffer = new byte[1024];
        byte[] dataSend;
        byte[] dataReceive;
        FilterDataManager filters;



        public MachineConnection()
        {
            sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            filters = new FilterDataManager();
        }
        public void Connect(IPAddress ipaddr, int port)
        {
            this.ipaddr_machine = ipaddr;
            this.port_machine = port;
            sock.BeginConnect(ipaddr, port, new AsyncCallback(OnConnect), null);
        }
        public void Disconnect()
        {
            if (sock.Connected)
                sock.Disconnect(true);
        }
        void OnConnect(IAsyncResult ar)
        {
            try
            {
                if (!ar.IsCompleted)
                {
                    sock.BeginConnect(ipaddr_machine, port_machine, new AsyncCallback(OnConnect), null);
                    return;
                }
                sock.EndConnect(ar);
                sock.BeginReceive(buffer, 0, 2, SocketFlags.None, new AsyncCallback(OnSizeReceive), null);
            }
            catch (System.Exception e)
            {

            }
        }

        #region Receive Data

        int SumSizeReceive = 0;
        int SizeReceived = 0;
        void OnSizeReceive(IAsyncResult ar)
        {
            try
            {
                if (!ar.IsCompleted)
                {
                    sock.BeginReceive(buffer, 0, 2, SocketFlags.None, new AsyncCallback(OnSizeReceive), null);
                    return;
                }
                sock.EndReceive(ar);
                SumSizeReceive = buffer[0];
                if (SumSizeReceive > 0)
                    sock.BeginReceive(buffer,2, SumSizeReceive, SocketFlags.None, new AsyncCallback(OnReceive), null);
                else
                    sock.BeginReceive(buffer, 0, 2, SocketFlags.None, new AsyncCallback(OnSizeReceive), null);
            }
            catch (System.Exception e)
            {

            }
        }
        void OnReceive(IAsyncResult ar)
        {
            try
            {
                if (!ar.IsCompleted)
                {
                    return;
                }
                SocketError error;
                int i = sock.EndReceive(ar, out error);
                if (i < 1)
                {
                    return;
                }
                SizeReceived += i;
                if (SizeReceived < SumSizeReceive)
                {
                    sock.BeginReceive(buffer, SizeReceived + 2, SumSizeReceive - SizeReceived, SocketFlags.None, new AsyncCallback(OnReceive), null);
                }
                else
                {
                    ProcessReceiveFullData();
                    ResetSumReceive();
                    sock.BeginReceive(buffer, 0, 2, SocketFlags.None, new AsyncCallback(OnSizeReceive), null);
                }



            }
            catch (Exception e)
            {

            }
        }

        void ResetSumReceive()
        {
            SumSizeReceive = 0;
            SizeReceived = 0;
            buffer = new byte[1024];
        }
        void ProcessReceiveFullData()
        {
            dataReceive = filters.ProcessDataReceive(buffer);
            if (Receive_From_Machine != null)
                Receive_From_Machine(this, new ReceiveFromMachineEventArgs(dataReceive, this));
        }
        #endregion

        #region Send Message

        public void SendMessage(byte[] message)
        {
            dataSend = filters.ProcessDataSend(message);
            sock.BeginSend(dataSend, 0, dataSend.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
        }

        public void SendMessage(MSG_GSM message,params object[] param)
        {
            List<byte> Data = new List<byte>();
            Data.Add((byte)message);
            foreach (object obj in param)
            {
                Data.Add((byte)(int)obj);
            }
            SendMessage(Data.ToArray());
        }

        public void SendMessage(MSG_GSM message, byte[] param)
        {
            List<byte> Data = new List<byte>();
            Data.Add((byte)message);
            Data.AddRange(param);
            SendMessage(Data.ToArray());
        }


        void OnSend(IAsyncResult ar)
        {
            try
            {
                if (!ar.IsCompleted)
                {
                    sock.BeginSend(dataSend, 0, dataSend.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
                    return;
                }
                sock.EndSend(ar);
            }
            catch (System.Exception e)
            {

            }
        }

        #endregion



        public event EventHandler<ReceiveFromMachineEventArgs> Receive_From_Machine;
    }
}
